﻿using System;
using log4net;
using Reactor.Environment;
using Reactor.Exceptions;
using Reactor.Messaging;

namespace Reactor.ServiceGrid
{
    public abstract class ReactorServiceBase : IReactorService
    {
        #region Fields

        protected static ILog Log;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ReactorServiceBase"/> class.
        /// </summary>
        protected ReactorServiceBase()
        {
            Log = LogManager.GetLogger(GetType());
        }

        #endregion

        #region Events

        /// <summary>
        /// Occurs when this instance has been started.
        /// </summary>
        public event EventHandler Started;

        /// <summary>
        /// Occurs when this instance is starting.
        /// </summary>
        public event EventHandler Starting;

        /// <summary>
        /// Gets or sets the identifier.
        /// </summary>
        /// <value>The identifier.</value>
        public ServiceIdentifier Identifier { get; set; }

        #endregion

        #region Public Methods

        /// <summary>
        /// Gets or sets the primary input queue.
        /// </summary>
        /// <value>The primary input queue.</value>
        public abstract PointToPointChannel PrimaryInputChannel { get; set; }

        /// <summary>
        /// Starts this instance.
        /// </summary>
        public virtual void Start()
        {
            Log.Info("Starting Reactor Service");

            try
            {
                if (Starting != null) Starting(this, EventArgs.Empty);

                //Instruct handler registry to discover handlers and initialize subscriptions.
                Context.ServiceBus.Configuration.MessageHandlerRegistry.ScanAssembliesForHandlers();

                //Startup service bus
                Context.ServiceBus.Start();

                // Obtain this service's record
                // TODO: service record!

                if (Started != null)
                    Started(this, EventArgs.Empty);
            }
            catch(Exception ex)
            {
                throw new FatalException("Unable to start service.", ex);
            }
        }

        /// <summary>
        /// Stops this instance.
        /// </summary>
        public virtual void Stop()
        {
            OnStopping();

            if(Context.ServiceBus != null)
                Context.ServiceBus.Stop();
        }

        #endregion

        /// <summary>
        /// Called when the instance is stopping. This signals for concrete implementations to perform 
        /// their own teardown.
        /// </summary>
        protected virtual void OnStopping() {}
    }
}
